#include <sys_config.h>
#include <retcode.h>
#include <types.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <bus/i2c/i2c.h>
#include <osal/osal.h>
#include "tun_tda18212.h"

#if ((SYS_TUN_MODULE == TDA18212) || (SYS_TUN_MODULE == ANY_TUNER))

#define TDA18212_DEBUG_FLAG	 0
#if(TDA18212_DEBUG_FLAG)
#define TDA18212_PRINTF     libc_printf
#else
#define TDA18212_PRINTF(...) 
#endif


static struct COFDM_TUNER_CONFIG_EXT Tda18212_TunerConfig[2];
static UINT32 tuner_cnt = 0;

extern INT32 i2c_gpio_write_no_stop(UINT32 id, UINT8 slv_addr, UINT8 *data, int len);
extern INT32 i2c_gpio_read_no_stop(UINT32 id, UINT8 slv_addr, UINT8 *data, int len);
extern INT32 i2c_gpio_mbyte_write_read(UINT32 id, UINT8 slv_addr, UINT8 *data, int wlen, int rlen);

extern void M3602_DB04V01_reset_tuner(void);


ID f_TDA18212_IIC_Sema_ID = OSAL_INVALID_ID;

unsigned int	tun_tda18212write(UINT8  uAddress,UINT8  uSubAddress,UINT8  uNbData, UINT8* pDataBuff)
{
	INT32 result;
	UINT8 data[uNbData+1];
	UINT8 u8_add;
	UINT8 u8_subadd;
	INT32 len;
	UINT8    buf[5]; 
	UINT8 i=0;


	osal_semaphore_capture(f_TDA18212_IIC_Sema_ID,TMO_FEVR);
	//osal_interrupt_disable();

	u8_add = 0x3C;//demod addr ;	
        buf[0]=0xFE; 	
        buf[1]=uAddress;//tuner sddr 
	 buf[2]=uSubAddress; //register addr
	 len = uNbData; 
	
        for(i=0;i<uNbData;++i) 
       {     
       	buf[3+i]=pDataBuff[i];	
        }

	//libc_printf("%x %x %x %x\n",u8_add,uSubAddress,uNbData,* pDataBuff);
          result= i2c_gpio_write(0,u8_add,buf,len+3); 

	//   if(result!=0)
	   	// libc_printf("Tuner_wr=%d\n",result);	
	
	osal_task_sleep(10);
	//osal_interrupt_enable();
	osal_semaphore_release(f_TDA18212_IIC_Sema_ID);

	return result;
}

unsigned int	tun_tda18212read(UINT8  uAddress, UINT8 uSubAddress,UINT8  uNbData,UINT8* pDataBuff)
{
	INT32 result;
	UINT8 data[59];		
    	UINT8 i;
	UINT8 u8_add;
	UINT8 u8_subadd;
	INT32 len;		
	
osal_semaphore_capture(f_TDA18212_IIC_Sema_ID,TMO_FEVR);
//osal_interrupt_disable();

	
	u8_add = 0x3C;//uAddress;		
	data[0]=0xFE;
	data[1]=uAddress;//target address
	data[2]=uSubAddress;//register addrs
#if 0	
  result=i2c_gpio_write_no_stop(1,u8_add, data, 3);
  // if(result!=0)
	   //	libc_printf("Tuner_rd=%d\n",result);
  	data[0]=0xFE;		
	data[1]=0xC0|0x1;

    result=i2c_gpio_write_no_stop(1,u8_add, data, 2);
  // if(result!=0)
	   //	libc_printf("Tuner_rd=%d\n",result);
  result=i2c_gpio_read_no_stop(1,u8_add, pDataBuff,uNbData);

   //osal_task_sleep(20);
   #else
 i2c_gpio_mbyte_write_read(0, u8_add, data, 3, uNbData);
 * pDataBuff= data[0];

 osal_task_sleep(10);
   #endif
//osal_interrupt_enable();
	osal_semaphore_release(f_TDA18212_IIC_Sema_ID);
	return result;

}


static int  sembsl_tda18272_wait_irq(UINT8 tuner_id) 
{ 
    int                         res=SEM_SOK; 
    UINT32                         cnt; 
    UINT8                          byte;      

 
    for(cnt=50;--cnt;) 
    { 
      tun_tda18212read(Tda18212_TunerConfig[tuner_id].cTuner_Base_Addr,0x08,1,&byte); 
      
        if(0x80&byte) break; 
        osal_task_sleep(300); 
    } 
    if(!cnt)  
    {
    	res|=SEM_ETIMEOUT;  
	TDA18212_PRINTF("IRQ timeout \n");
    }
    return res; 
} 


static int  sembsl_tda18272_sleep(UINT8 tuner_id)      
{ 
    int	res=SEM_SOK; 
 
    UINT8	byte=0x08;  
  
      tun_tda18212write(Tda18212_TunerConfig[tuner_id].cTuner_Base_Addr,0x06,1,&byte); 

    return res; 
} 
 
  
static int  sembsl_tda18272_get_rf_strength( UINT8 tuner_id ,  UINT16  *strength ) 
{ 
    int                         res=SEM_SOK; 
 
    UINT8                          bytes[4]; 
     
    *strength=0;    

	res|=tun_tda18212read(Tda18212_TunerConfig[tuner_id].cTuner_Base_Addr,0x07,1,bytes);  
    *strength=(UINT16)((bytes[0]<<8));  
    return res; 
} 
 
static int  sembsl_tda18272_get_id(UINT8 tuner_id ) 
{
    int                         res=SEM_SOK; 
 
    UINT32                         id=0; 
    UINT8                          bytes[2]; 
 

    res|=tun_tda18212read(Tda18212_TunerConfig[tuner_id].cTuner_Base_Addr,0x00,0x02,bytes);   
 
    id=((bytes[0]<<8)|bytes[1])&0x7FFF; 
	
    if(0xC7!=bytes[0]) 
		res|=SEM_EIIC_NOACK; 
	
    if(18272!=id && 18212!=id ) 
		res|=SEM_EIIC_NOACK; 
 
    return res; 
} 

/*****************************************************************************
* INT32 tun_tda18212_init(struct COFDM_TUNER_CONFIG_EXT * ptrTuner_Config)
*
* Tuner tda18212 Initialization
*
* Arguments:
*  Parameter1: struct COFDM_TUNER_CONFIG_EXT * ptrTuner_Config		: pointer for Tuner configuration structure 
*
* Return Value: INT32			: Result
*****************************************************************************/
INT32 tun_tda18212_init(UINT32 *tuner_id, struct COFDM_TUNER_CONFIG_EXT * ptrTuner_Config)
{
    UINT8 i=0,tmp=0;
    if ((ptrTuner_Config == NULL) || tuner_cnt >= MAX_TUNER_SUPPORT_NUM)
        return ERR_FAILUE;

    if(tuner_cnt >= MAX_TUNER_SUPPORT_NUM)
        return ERR_FAILUE;

    MEMCPY(&Tda18212_TunerConfig[tuner_cnt], ptrTuner_Config, sizeof(struct COFDM_TUNER_CONFIG_EXT));
        
    f_TDA18212_IIC_Sema_ID=osal_semaphore_create(1);
    if(f_TDA18212_IIC_Sema_ID==OSAL_INVALID_ID)
    {
        TDA18212_PRINTF("TN create Sema fail ! \n ");
    }
//  while(0)
    {
        for(i=0;i<(sizeof(_ary_init_isdbt))/2;i++)  
        {
            tun_tda18212write(Tda18212_TunerConfig[0].cTuner_Base_Addr,_ary_init_isdbt[2*i],1,&_ary_init_isdbt[2*i+1]);

            tun_tda18212read(Tda18212_TunerConfig[0].cTuner_Base_Addr,_ary_init_isdbt[2*i],1,&tmp);
            TDA18212_PRINTF("TN !reg[%x]=%x\n",_ary_init_isdbt[2*i],tmp);
        }  
    }
    sembsl_tda18272_wait_irq(tuner_cnt);    
    
    //tuner_id = (UINT8)tuner_cnt;
    tuner_cnt++;

    return SUCCESS;
}

/*****************************************************************************
* INT32 tun_tda18212_status(UINT8 *lock)
*
* Tuner read operation
*
* Arguments:
*  Parameter1: UINT8 *lock		: Phase lock status
*
* Return Value: INT32			: Result
*****************************************************************************/

INT32 tun_tda18212_status(UINT32 tuner_id, UINT8 *lock)
{
	INT32 result;
	UINT8 data;	
	UINT8 byte=0;	


	//struct COFDM_TUNER_CONFIG_EXT *ptrTuner_Config;

	if (tuner_id >= tuner_cnt || tuner_id >= MAX_TUNER_SUPPORT_NUM)
	{
		*lock = 0;
		return ERR_FAILUE;
	}

	   result|=tun_tda18212read(Tda18212_TunerConfig[0].cTuner_Base_Addr,0x05,0x01,&byte);
	   result|=sembsl_tda18272_wait_irq(tuner_id); 
    	if(byte&0x01)  
			*lock =1; 
	else
			*lock =0;

	TDA18212_PRINTF("byte= %x ,LK=%d\n",byte,*lock );
	//ptrTuner_Config = Tda18212_TunerConfig[tuner_id];	
	
	//result = ptrTuner_Config->Tuner_Read(ptrTuner_Config->i2c_type_id,ptrTuner_Config->cTuner_Base_Addr, &data, 1);
	return result;
}

/*****************************************************************************
* INT32 nim_tda18212_control(UINT32 freq, UINT8 bandwidth,UINT8 AGC_Time_Const,UINT8 *data,UINT8 _i2c_cmd)
*
* Tuner write operation
*
* Arguments:
*  Parameter1: UINT32 freq		: Synthesiser programmable divider
*  Parameter2: UINT8 bandwidth		: channel bandwidth
*  Parameter3: UINT8 AGC_Time_Const	: AGC time constant
*  Parameter4: UINT8 *data		: 
*
* Return Value: INT32			: Result
*****************************************************************************/
INT32 tun_tda18212_control(UINT32 tuner_id, UINT32 freq, UINT8 bandwidth,UINT8 AGC_Time_Const,UINT8 *data,UINT8 _i2c_cmd)	
{
	INT32 result;
	UINT8 tmp; 
	UINT16 Npro;	
	UINT32 freq1;
	UINT8 CP2_0, SP5, SP4, SP3_1, ATC, R2_0, AL2_0;
        UINT32 err=0;
	UINT8 bytes[5];

	UINT8 i;

	freq=freq-143;
	//struct COFDM_TUNER_CONFIG_EXT *ptrTuner_Config;

	if (tuner_id >= tuner_cnt || tuner_id >= MAX_TUNER_SUPPORT_NUM)
	{
		return ERR_FAILUE;
	}	

#if 1
	 if(freq< 291000)  
        {  
		 for(i=0;i<(sizeof(_ary_isdbt_6mhz_vh))/2;i++)  
    		{
			tun_tda18212write(Tda18212_TunerConfig[0].cTuner_Base_Addr,_ary_isdbt_6mhz_vh[2*i],1,&_ary_isdbt_6mhz_vh[2*i+1]);
			tun_tda18212read(Tda18212_TunerConfig[0].cTuner_Base_Addr,_ary_isdbt_6mhz_vh[2*i],1,&tmp);
			TDA18212_PRINTF(">>TN VH!reg[%x]=%x\n",_ary_init_isdbt[2*i],tmp);
    		}         
        }  
        else  
        {  
	        //while(1)
	        {
	        	 for(i=0;i<(sizeof(_ary_isdbt_6mhz_uhf))/2;i++)  
	    		{
				tun_tda18212write(Tda18212_TunerConfig[0].cTuner_Base_Addr,_ary_isdbt_6mhz_uhf[2*i],1,&_ary_isdbt_6mhz_uhf[2*i+1]);
				tun_tda18212read(Tda18212_TunerConfig[0].cTuner_Base_Addr,_ary_isdbt_6mhz_uhf[2*i],1,&tmp);
				TDA18212_PRINTF(">>TN UH !reg[%x]=%x\n",_ary_isdbt_6mhz_uhf[2*i],tmp);
	    		}     
	        }
        } 
#endif

	bytes[0]=(UINT8)((freq>>16)&0xFF); 
    	bytes[1]=(UINT8)((freq>> 8)&0xFF); 
    	bytes[2]=(UINT8)((freq   )&0xFF); 
    	bytes[3]=(UINT8)(0xC1); 
    	bytes[4]=(UINT8)(0x01); 
		
    	tun_tda18212write(Tda18212_TunerConfig[0].cTuner_Base_Addr,0x16,5,bytes); 
		
  	sembsl_tda18272_wait_irq(tuner_id); 
	
	return SUCCESS;	
}

#endif





